# This file is part of the AutoMAT distribution (https://bitbucket.com/mahomaho/AutoMAT).
# Copyright (c) 2020 Mattias Holmqvist.
# 
# AutoMAT is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# AutoMAT is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with AutoMAT.  If not, see <https://www.gnu.org/licenses/>.
from collections import defaultdict, OrderedDict
import os
import signal
import sys

import argparse
import time
start_time = time.time()

if __name__ == "__main__":
	
	parser = argparse.ArgumentParser(description='AutoMAT arxml script tool', prog='AutoMAT')
	parser.add_argument('-s', '--scripts', nargs='*', help='script files to be executed. It is also possible to pass arguments to the script. To do so, surround the script and arguments with quotations', default=[])
	
	parser.add_argument('-d', '--debug', action='store_true', help='debug mode, add more trace output e.g. call stack in case of segmentation fault', default=False)
	#parser.add_argument('-D', '--enironment_debug', action='store_true', help='debug mode, reload environment on every debug rerun', default=False)
	parser.add_argument('-v', '--verbose', action='store_true', help='enable debug printouts', default=False)
	#parser.add_argument('-n', '--no_validation', action='store_true', help='disable arxml content schema validation', default=False)
	parser.add_argument('-e', '--stop_on_error', action='store_true', help='return on first script error instead of finish all scripts', default=False)
	parser.add_argument('-p', '--extra_paths', nargs='*', help='directories to be appended to the path environment variable when scripts are executed', default=[])
	
	#parser.add_argument('-j', '--processes', nargs='?', type=int, help='max number of processes used to parse the model', default=None)
	parser.add_argument('-a', '--arxml', nargs='*', help='individual arxml files to load', default=[])
	parser.add_argument('-l', '--dirs', nargs='*', help='dirs to search for arxmls to load', default=[])
	parser.add_argument('-L', '--basedirs', nargs='*', help='dirs to search for arxmls recursively for files to load', default=[])
	
	parser.add_argument('-R', '--autosar_release', choices=['AUTOSAR_4-2-2.xsd', 'AUTOSAR_00046.xsd', 'AUTOSAR_00048.xsd', 'AUTOSAR_00049.xsd', 'AUTOSAR_00052.xsd'], default='AUTOSAR_00052.xsd', help='AUTOSAR release schema version')
	
	args = parser.parse_args()
	
	os.environ['AUTOSAR_RELEASE']=args.autosar_release[:-4]
	from AutoMAT import *
	
	if args.debug:
		import faulthandler
		faulthandler.enable()
	
	if args.verbose:
		import AutoMAT
		AutoMAT._vprint=print
	from AutoMAT import _vprint as vprint
	
	for dir in args.dirs:
		try:
			files = (os.path.join(dir, name) for name in os.listdir(dir) if name.endswith(".arxml"))
			args.arxml.extend(files)
		except FileNotFoundError:
			print(f'Specified path {dir} does not exist\n')
	for dir in args.basedirs:
		files = (os.path.join(root, name) for root, dirs, files in os.walk(dir) for name in files if name.endswith(".arxml"))
		args.arxml.extend(files)
	
	for arxml in args.arxml:
		LoadFile(arxml)
		
	sys.path.append('')
	# add the extra paths
	for path in args.extra_paths:
		assert os.path.isdir(path), f'The specified path {path} is not a valid path'
		sys.path.append(path)
		
	import traceback
	numerrs=0
	exitcode=0
	for script in args.scripts:
		if exitcode and args.stop_on_error:
			break
		try:
			vprint('execute :' + script)
			script = script.split()
			scriptpath=os.path.abspath(script[0])
			scriptname=os.path.basename(os.path.splitext(scriptpath)[0])
			sys.path.append(os.path.dirname(scriptpath))
			if scriptpath.endswith('.py'):
				from importlib.machinery import EXTENSION_SUFFIXES
				for suffix in EXTENSION_SUFFIXES:
					if os.path.exists(scriptpath[:-3]+suffix):
						scriptpath = scriptpath[:-3]+suffix
						from importlib.machinery import ExtensionFileLoader
						fileLoader = ExtensionFileLoader
						break
				else:
					from importlib.machinery import SourceFileLoader
					fileLoader = SourceFileLoader
			mymodule = SourceFileLoader('script', scriptname).load_module()
			if hasattr(mymodule,'main'):
				ret=mymodule.main(script[1:])
				#if isinstance(ret,int) and ret > 0:
				if ret:
					numerrs+=1
					if exitcode == 0:
						if isinstance(ret,int):
							exitcode = ret
						else:
							exitcode = 1
		except SystemExit as e:
			if e.code:
				print(f'Script {scriptname} exited with error code: {e.code}\n')
				numerrs+=1
				if exitcode == 0:
					exitcode = e.code
		except Exception as e:
			print(f'Script {scriptname} exited with error:')
			if args.verbose:
				print(traceback.format_exc())
			else:
				print(str(e))
			numerrs+=1
			if exitcode==0:
				exitcode=1
		try:
			sys.path.remove(os.path.dirname(scriptname))
			del sys.modules['script']
		except: pass
	
	if exitcode>0:
		sys.exit(exitcode)
		
	vprint("all scripts run, total execution time was %s seconds" % (time.time() - start_time))
	sys.exit(exitcode)
